﻿using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
using Volo.Abp.Uow;

namespace PHMEE.Admin
{
    /// <summary>
    /// 采集站配置数据服务
    /// </summary>
    public class SysParaAppService : PHMEEAdminAppService, ISysParaAppService
    {
        private readonly ILogger<SysParaAppService> _logger;
        private readonly ISensorRepository _sensorRepository;
        private ISysParaManager _sysParaManager;
        private IGuidGenerator _guidGenerator;
        private readonly IDataFilter _dataFilter;
        private readonly ISysParaRepository _sysParaRepository;
        private readonly ISysParaExtendRepository _sysParaExtendRepository;
        private readonly RedisHelper _redisHelper;

        public SysParaAppService(ISysParaManager sysParaManager, IGuidGenerator guidGenerator, ISysParaRepository sysParaRepository, IDataFilter dataFilter, RedisHelper redisHelper, ISysParaExtendRepository sysParaExtendRepository, ILogger<SysParaAppService> logger, ISensorRepository sensorRepository)
        {
            _logger = logger;
            _sysParaManager = sysParaManager;

            _guidGenerator = guidGenerator;
            _sysParaRepository = sysParaRepository;
            _dataFilter = dataFilter;
            _redisHelper = redisHelper;
            _sysParaExtendRepository = sysParaExtendRepository;
            _sensorRepository = sensorRepository;
        }

        /// <summary>
        /// 根据id查询采集站--双击查看用
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<SysParaByIdDto> GetByIdAsync(Guid id)
        {
            var sysPara = await _sysParaRepository.GetAsync(id);

            var sysParaDto = ObjectMapper.Map<SysPara, SysParaByIdDto>(sysPara);
            sysParaDto.SamplingFrequency = sysParaDto.SamplingFrequency;
            return sysParaDto;
        }
        /// <summary>
        /// 根据采集站编码查询采集站--采集站下发用
        /// </summary>
        /// <param name="collectorCode">采集站编码</param>
        /// <returns></returns>
        public async Task<SysParaDto> GetByIdUseMqttAsync(string collectorCode)
        {
            var queryable = await _sysParaRepository.GetQueryableAsync();
            queryable = queryable.Where(item => item.CollectorCode == collectorCode);
            var sysPara = queryable.FirstOrDefault();
            //sysPara.WavePeriod=sysPara.WavePeriod*;
            return ObjectMapper.Map<SysPara, SysParaDto>(sysPara);
        }
        /// <summary>
        /// 插入策略参数数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<SysParaListDto> CreateSysParaAsync(SysParaCreateDto input)
        {

            var sysPara = await _sysParaManager.CreateSysPara(input.CollectorCode, input.SamplingPeriod);
            input.SamplingFrequency = input.SamplingFrequency;
            ObjectMapper.Map(input, sysPara);
            await _sysParaRepository.InsertAsync(sysPara, autoSave: true);
            var indexSyaPara = await _sysParaRepository.GetAsync(sysPara.Id);
            return ObjectMapper.Map<SysPara, SysParaListDto>(indexSyaPara);
        }
        /// <summary>
        /// 获取采集站的列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<SysParaListResultDto> GetAllSysParaAsync(PageSysParaDto input)
        {
            var sysParaQuery = await _sysParaRepository.GetQueryableAsync();
            var sysParaExtendQuery = await _sysParaExtendRepository.GetQueryableAsync();
            var queryable = from sysPara in sysParaQuery
                            join sysParaExtend in sysParaExtendQuery
                            on sysPara.CollectorCode equals sysParaExtend.Code into extendJoin
                            from extend in extendJoin.DefaultIfEmpty()
                            select new
                            {
                                sysPara,
                                extend.LocalIp
                            };
            if (!string.IsNullOrEmpty(input.CollectorCode))
            {
                queryable = queryable.Where(item => item.sysPara.CollectorCode == input.CollectorCode);
            }

            switch (input.olineStatus)
            {
                case OlineStatusEnum.Online:
                    queryable = queryable.Where(item => item.sysPara.IsOnline == true);
                    break;
                case OlineStatusEnum.Offline:
                    queryable = queryable.Where(item => item.sysPara.IsOnline == false);
                    break;
                default:
                    break;
            }
            queryable = queryable.OrderBy(x => x.sysPara.CollectorCode);
            if (input.IsPaged)
            {
                queryable = queryable.Skip(input.SkipCount).Take(input.MaxResultCount);
            }
            var sysParaList = await AsyncExecuter.ToListAsync(queryable);

            var totalCount = await _sysParaRepository.GetCountAsync();
            var onlineCount = await _sysParaRepository.GetOnlineCountAsync();
            var offlineCount = totalCount - onlineCount;

            var sysParaListDtos = sysParaList.Select(x => new SysParaListDto
            {
                Id = x.sysPara.Id,
                CollectorType = x.sysPara.CollectorType,
                CollectorCode = x.sysPara.CollectorCode,
                CreateTime = x.sysPara.CreateTime,
                ParaTime = x.sysPara.ParaTime,
                LocalIp = x.LocalIp,
                IsOnline = x.sysPara.IsOnline
            }).ToList();

            return new SysParaListResultDto
            {
                TotalCount = totalCount,
                OnlineCount = onlineCount,
                OfflineCount = offlineCount,
                Items = sysParaListDtos
            };
        }
        /// <summary>
        /// 更新采集站信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task UpdateAsync(SysParaUpdateDto input)
        {
            var sysPara = await _sysParaRepository.GetAsync(input.Id);
            input.SamplingFrequency = input.SamplingFrequency;
            ObjectMapper.Map(input, sysPara);

            sysPara.TechPeriod = input.SamplingPeriod;
            sysPara.RpmPeriod = input.SamplingPeriod;
            sysPara.RtuPeriod = input.SamplingPeriod;

            await _sysParaRepository.UpdateAsync(sysPara);
        }
        /// <summary>
        /// 删除采集站信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync(Guid id)
        {
            //await _sysParaRepository.DeleteAsync(id);
            // 临时禁用软删除过滤器
            using (_dataFilter.Disable<ISoftDelete>())
            {
                var sysPara = await _sysParaRepository.FindAsync(id);
                if (sysPara != null)
                {
                    await _sysParaRepository.DeleteAsync(sysPara);
                }
                else
                {
                    throw new EntityNotFoundException(typeof(SysPara), id);
                }
            }
        }
        /// <summary>
        /// 创建数采器扩展信息并且更新数采器信息
        /// </summary>
        /// <returns></returns>
        [UnitOfWork]
        public async Task CreateSysParaExtendAndUpdateSyspara(CreateSysParaExtendDto createSysParaExtendDto)
        {
            try
            {
                // 1.如果存在数采器创建的信息，下发参数时间赋值，否则不处理
                await _sysParaRepository.SetParaTimeAsync(createSysParaExtendDto.Code);
                // 2.如果存在数采器创建的信息，数采器注册时标记为在线状态
                await _sysParaRepository.UpdataOnlineStatueAsync(createSysParaExtendDto.Code, true);
                // 3.根据数采器编号获取当前扩展记录
                var existingSysParaExtend = await _sysParaExtendRepository.GetSysParaExtendAsync(createSysParaExtendDto.Code);
                // 4.如果存在，删除当前扩展记录
                if (existingSysParaExtend != null)
                {
                    await _sysParaExtendRepository.DeleteAsync(existingSysParaExtend);
                }
                // 5.实体映射
                var newSysParaExtend = ObjectMapper.Map<CreateSysParaExtendDto, SysParaExtend>(createSysParaExtendDto);
                // 6.插入新扩展记录数据
                await _sysParaExtendRepository.InsertAsync(newSysParaExtend, true);
                _logger.LogInformation($"创建数采器扩展信息{createSysParaExtendDto.Code}成功！");
            }
            catch (Exception ex)
            {
                _logger.LogInformation($"创建数采器扩展信息{createSysParaExtendDto.Code}失败！", ex.Message);
            }
        }
        /// <summary>
        /// 根据采集器编码查看扩展信息
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<SysParaExtendDto> GetSyaParaExtendAsync(string code)
        {
            var sysParaExtend = await _sysParaExtendRepository.GetSysParaExtendAsync(code);
            return ObjectMapper.Map<SysParaExtend, SysParaExtendDto>(sysParaExtend);
        }
    }
}
